class_name BaseLevel
extends Node

var camera_offset := Vector2.ZERO
var camera_zoom := Vector2.ZERO
var shake_strength: float = 0.0
@export var camera_covery_speed: float = 16.0

@onready var camera_2d: Camera2D = $Player/Camera2D
@onready var map: TileMapLayer = $Map
@onready var debug_hud: CanvasLayer = $DebugHUD
@onready var blur_vignette: ColorRect = $CanvasLayer/BlurVignette
@onready var player: Player = %Player


func reset_player(direction: int = 0, is_entering: bool = false, mode := Player.EnteringMode.NORMAL):
	%Player.position = GlobalGameData.playerRespawnPoints[-1].pos
	%Player.direction = %Player.direction if direction == 0 else direction
	%Player.resetPlayerToFloor()
	if is_entering:
		%Player.enter_new_scene(%Player.direction, mode)
		GlobalGameData.playerRespawnPoints.pop_back()
	else:
		%Player.teleport_player.play("spawn")
	camera_2d.reset_smoothing()
	camera_2d.force_update_scroll()


func init_interactables() -> void:
	pass


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	%Player.position = $PlayerSpanPos.position
	%Player.show()
	GlobalGameData.playerRespawnPoints.append({
		pos=$PlayerSpanPos.position,
		name="INIT"
	})
	
	var used = map.get_used_rect().grow(-1)
	var tileSize = map.tile_set.tile_size
	
	# 自动计算地图的边距
	camera_2d.limit_top = used.position.y * tileSize.y
	camera_2d.limit_bottom = used.end.y * tileSize.y
	camera_2d.limit_left = used.position.x * tileSize.x
	camera_2d.limit_right = used.end.x * tileSize.x
	
	# 避免相机在场景最开始“平滑”移动到limit中
	camera_2d.reset_smoothing()
	
	# blur_vignette.show()  # 暂时禁用，某些移动端不能正确渲染这个shader
	debug_hud.show()
	
	## TODO: 将遍历节点寻找目标节点的方式改为搜索目标节点所属group的方式
	for node in get_tree().get_nodes_in_group("damage_area"):
		node = node as DamageArea
		if node:
			node.reset_player.connect(on_player_damaged.bind(node))
	for node in get_tree().get_nodes_in_group("mobs"):
		node.reset_player.connect(on_player_hit.bind(node))
	for node in get_tree().get_nodes_in_group("check_points"):
		Game.update_checkpoints.connect(node.update_state)
	
	init_interactables()

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	var shake_offset := Vector2(
		randf_range(-shake_strength, shake_strength),
		randf_range(-shake_strength, shake_strength)
	)
	camera_2d.offset = shake_offset + camera_offset
	shake_strength = move_toward(shake_strength, 0, camera_covery_speed * delta)


func on_player_damaged(node) -> void:
	if GlobalGameData.change_hp(-node.damage) == -1:
		%Player.freeze()
		return
	reset_player()
	%Player.freeze()
	shake_strength += node.camera_shake_strength


func on_player_hit(node) -> void:
	if %Player.is_protected:
		return  # 无敌时间保护
	if GlobalGameData.change_hp(-node.damage) == -1:
		%Player.freeze()
		return
	%Player.init_knock_back_on_damage()
	shake_strength += node.camera_shake_strength


func _unhandled_input(event: InputEvent) -> void:
	if event.is_action_pressed("ui_reset"):
		if not %Player.is_entering: reset_player()
	
	if event.is_action_pressed("pause") and not %Player.is_dead:
		%Player/PauseScreen.show_pause()
